<?php

namespace MrHd\LJsTan;
use Exception;
use GuzzleHttp\Exception\GuzzleException;
use MrHd\LJsTan\Http\Http;


class Client extends JsTanInIt
{
    private static ?Client $instance = null;

    /**
     * @param string $url
     * @param array $data
     * @return array
     */
    private function post(string $url,array $data): array
    {
        $config = $this->getConfig();
        $http = Http::getInstance($config)->getClient();
        try {
            $response = $http->post(
                $url,[
                    'form_params' => $data
                ]
            );
            $result = $response->getBody()->getContents();
            $result = json_decode($result,true);
            if(!$result){$result = array();}
            return $result;
        } catch (GuzzleException|Exception $e) {
            return array(
                'code'=>'-100',
                'exception'=>$e->getMessage(),
                'msg'=>$e->getMessage()
            );
        }
    }

    /**
     * @param string $url
     * @param array $data
     * @param string $access_token
     * @return Exception|string|GuzzleException
     * 请求接口
     */
    public function request(string $url,array $data,$access_token=''): array
    {
        $config = $this->getConfig();
        $publicRequestParams = $this->getPublicRequestParams();
        if($access_token){
            $publicRequestParams['access_token'] = $access_token;
        }
        $params = Util::getInstance($publicRequestParams)->getParams($config['appSecret'], $data);
        if(stripos($url,'http://')===false&&stripos($url,'https://')===false){
            $url = trim($config['apiUrl'],'/').$url;
        }
        return $this->post($url, $params);
    }

    /**
     * 获得签名
     * @Description 获得签名
     * @param $data
     * @return string|null
     * @Author Mr.d
     * @DateTime 2024/4/10 0010 23:25
     */
    public function getSign($data): ?string
    {
        $config = $this->getConfig();
        return Util::getSign($config['appSecret'],$data);
    }

    /**
     * 更新配置
     * @Description 更新配置
     * @param array $data
     * @return void
     * @Author Mr.d
     * @DateTime 2024/4/11 0011 10:49
     */
    public function updateConfig($data=array())
    {
        if(!$data||!is_array($data))return;
        $config = $this->getConfig();
        $config = array_merge($config,$data);
        $this->setConfig($config);
    }

    /**
     * 获得配置信息
     * @Description 获得配置信息
     * @return array
     * @Author Mr.d
     * @DateTime 2024/4/11 0011 10:48
     */
    public function getConfig(): array
    {
        return parent::getConfig();
    }

    /**
     * @return string
     * 获取第三方授权拼接链接
     */
    public function createAuthUrl($state=''): string
    {
        $config = $this->getConfig();
        $data = [
            'app_key' =>$config['appKey'],
            'timestamp' => time(),
            'charset' => $config['charset']
        ];
        if($state){
            $data['state']=$state;
        }
        $stateStr = $state?'&state='.$state:'';
        $sign = Util::getSign($config['appSecret'],$data);
        return $config['authUrl'] .
            '?app_key=' . $data['app_key'] .
            '&timestamp=' . $data['timestamp'] .
            '&charset=' . $data['charset'] .
            '&sign=' . $sign.$stateStr;
    }

    /**
     * @param $code
     * @return Exception|string|GuzzleException
     * 获取access_token（getInitToken）[商家自研系统授权流程](https://openweb.jushuitan.com/doc?docId=23)
     */
    public function getInitToken($code): array
    {
        $data = [
            'app_key' => $this->getConfig()['appKey'],
            'timestamp' => time(),
            'grant_type' => 'authorization_code',
            'charset' => $this->getConfig()['charset'],
            'code' => $code,
        ];
        $data['sign'] = Util::getSign($this->getConfig()['appSecret'],$data);
        $url = $this->getConfig()['isProd']?'openWeb/auth/getInitToken':'openWebIsv/auth/getInitToken';
        return $this->post($this->getConfig()['apiUrl']. $url, $data);
    }

    /**
     * @param $code
     * @return Exception|string|GuzzleException
     * 获取access_token（accessToken）[第三方授权流程](https://openweb.jushuitan.com/doc?docId=25)
     */
    public function getAccessToken($code): array
    {
        $data = [
            'app_key' => $this->getConfig()['appKey'],
            'timestamp' => time(),
            'grant_type' => 'authorization_code',
            'charset' => $this->getConfig()['charset'],
            'code' => $code,
        ];
        $data['sign'] = Util::getSign($this->getConfig()['appSecret'],$data);
        $url = $this->getConfig()['isProd']?'openWeb/auth/accessToken':'openWebIsv/auth/accessToken';
        return $this->post($this->getConfig()['apiUrl']. $url, $data);
    }

    /**
     * @param $refreshToken
     * @return Exception|string|GuzzleException
     * 商家自研刷新access_token，第三方授权不可以刷新access_token(https://openweb.jushuitan.com/doc?docId=23)
     */
    public function refreshToken($refreshToken): array
    {
        $data = [
            'app_key' => $this->getConfig()['appKey'],
            'timestamp' => time(),
            'grant_type' => 'refresh_token',
            'charset' => $this->getConfig()['charset'],
            'refresh_token' => $refreshToken,
            'scope' => 'all',
        ];

        $data['sign'] = Util::getSign($this->getConfig()['appSecret'],$data);
        $url = $this->getConfig()['isProd']?'openWeb/auth/refreshToken':'openWebIsv/auth/refreshToken';
        return $this->post($this->getConfig()['apiUrl']. $url, $data);
    }

    /**
     * @param array $config
     * @return Client
     * 获取实例
     */
    public static function getInstance(array $config = []): Client
    {
        if(self::$instance == null ||self::$instance->getConfig() !== $config ){
            self::$instance = new self($config);
        }
        return self::$instance;
    }

}
